/*
Iterator
Iterator trait 用来对集合(collection) 类型(比如数组)实现迭代器。
这个trait只需要定一个返回 next 元素的方法，这可手动在impl 代码块中定义，
或者自动定义(比如在数组或区间中)

为方便， for 结构会使用 .into_iter() 方法将一些集合类型转换为迭代器
*/

struct Fibonacci {
    curr: u32,
    next: u32,
}

// 为 `Fibonacci` 实现 `Iterator`
impl Iterator for Fibonacci {
    type Item = u32;

    // 我们在这里使用 `.curr` 和 `.next` 来定义数列（sequence）
    // 返回类型为 `Option<T>`：
    //    * 当 `Iterator` 结束时，返回 `None`
    //    * 其他情况，返回被 `Some` 包裹（wrap）的下一个值
    fn next(&mut self) -> Option<u32> {
        let new_next = self.curr + self.next;

        self.curr = self.next;
        self.next = new_next;

        // 既然斐波那契数列不存在终点，那么 `Iterator` 将不可能
        // 返回 `None`，而总是返回 `Some`
        Some(self.curr)
    }
}

// 返回一个 Fibonacci 数列生成器
fn fibonacci() -> Fibonacci {
    Fibonacci {
        curr: 1,
        next: 1
    }
}

fn main() {
    // `0..3` 是一个 `Iterator`，会产生：0、1 和 2
    let mut sequence = 0..3;

    println!("Four consecutive `next` calls on 0..3");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // for 遍历 Iterator` 直到返回 `None`
    // 并且每个 `Some` 值都被解包（unwrap），然后绑定给一个变量（这里是 `i`）
    println!("Iterate through 0..3 using `for`");
    for i in 0..3 {
        println!("> {}", i);
    }

    // `take(n)` 方法提取 `Iterator` 的前 `n` 项
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // `skip(n)` 方法移除前 `n` 项，从而缩短了 `Iterator`
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // `iter` 方法对数组/slice 产生一个 `Iterator`
    println!("Iterate the following array {:?}", &array);
    for i in array.iter() {
        println!("> {}", i);
    }
}